using System.IdentityModel.Tokens.Jwt;
using _2GrpcUse.Services;
using System.IO.Compression;
using System.Security.Claims;
using K4os.Compression.LZ4;
using K4os.Compression.LZ4.Streams;
using Microsoft.AspNetCore.Authentication.JwtBearer;
using Microsoft.IdentityModel.Tokens;
using ICompressionProvider = Grpc.Net.Compression.ICompressionProvider;

//grpc-dotnet
//微软文档 https://learn.microsoft.com/zh-cn/aspnet/core/grpc/?view=aspnetcore-9.0
//用例 https://github.com/grpc/grpc-dotnet/tree/master/examples
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddAuthorization(options =>
{
    options.AddPolicy(JwtBearerDefaults.AuthenticationScheme, policy =>
    {
        policy.AddAuthenticationSchemes(JwtBearerDefaults.AuthenticationScheme);
        policy.RequireClaim(ClaimTypes.Name);
    });
});
builder.Services.AddAuthentication()
    .AddJwtBearer(options =>
    {
        options.TokenValidationParameters =
            new TokenValidationParameters
            {
                ValidateAudience = false,
                ValidateIssuer = false,
                ValidateActor = false,
                ValidateLifetime = true,
                IssuerSigningKey = SecurityKey
            };
    });
builder.Services.AddGrpc(o =>
{
    //侦听器，用于处理调用的切面，注意：执行会按注册顺序
    o.Interceptors.Add<ServerLoggerInterceptor>();
    //启动详细的异常信息！！生产环境禁用！！
    o.EnableDetailedErrors = true;

    //从客户端接收的最大消息大小（以字节为单位）。默认4MB，设设置为 null时，消息的大小不受限制。
    o.MaxReceiveMessageSize = 4 * 1024 * 1024;
    //可以从服务器发送的最大消息大小（以字节为单位）。
    //尝试发送超过配置的最大消息大小的消息会导致异常。默认位null, 设置为 null时，消息的大小不受限制。
    o.MaxSendMessageSize = null;

    //如果为 true，则对未知服务和方法的调用不会返回 UNIMPLEMENTED 状态，并且请求会传递到 ASP.NET Core 中的下一个注册中间件。
    o.IgnoreUnknownServices = true;

    //添加压缩器
    o.CompressionProviders.Add(LZ4CompressionProvider.Instance);
    //响应压缩级别，提供给压缩器使用
    o.ResponseCompressionLevel = CompressionLevel.Fastest;
    //指定压缩算法。请求grpc-accept-encoding头值必须包含此算法才能使用。
    o.ResponseCompressionAlgorithm = LZ4CompressionProvider.Instance.EncodingName;
});
var app = builder.Build();
app.MapGrpcService<OrderService>();
app.MapGet("/", () => "Communication with gRPC endpoints must be made through a gRPC client. To learn how to create a client, visit: https://go.microsoft.com/fwlink/?linkid=2086909");

app.Run();
return;

//自定义压缩器进行二进制流压缩，这里举例LZ4
public class LZ4CompressionProvider : ICompressionProvider
{
    public static LZ4CompressionProvider Instance { get; } = new();

    //压缩
    public Stream CreateCompressionStream(Stream stream, CompressionLevel? compressionLevel)
    {
        return LZ4Stream.Encode(stream);
    }

    //解压缩
    public Stream CreateDecompressionStream(Stream stream)
    {
        return LZ4Stream.Decode(stream);
    }

    public string EncodingName { get; } = "lz4";
}



public partial class Program
{
    private static readonly JwtSecurityTokenHandler JwtTokenHandler = new JwtSecurityTokenHandler();
    private static readonly SymmetricSecurityKey SecurityKey = new SymmetricSecurityKey(Guid.NewGuid().ToByteArray());
    
    static string GenerateJwtToken(string name)
    {
        if (string.IsNullOrEmpty(name))
        {
            throw new InvalidOperationException("Name is not specified.");
        }

        var claims = new[] { new Claim(ClaimTypes.Name, name) };
        var credentials = new SigningCredentials(SecurityKey, SecurityAlgorithms.HmacSha256);
        var token = new JwtSecurityToken("ExampleServer", "ExampleClients", claims, expires: DateTime.Now.AddSeconds(60), signingCredentials: credentials);
        return JwtTokenHandler.WriteToken(token);
    }
}
